package cn.com.code.design;

import cn.com.code.design.annotation.DoDoor;
import cn.com.code.design.config.StarterService;
import com.alibaba.fastjson.JSON;
import org.apache.commons.beanutils.BeanUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author zhengpei
 * @date 2021/9/29
 */
@Aspect
@Component
public class DoJoinPoint {

  private Logger logger = LoggerFactory.getLogger(DoJoinPoint.class);

  @Autowired
  private StarterService starterService;

  @Pointcut("@annotation(cn.com.code.design.annotation.DoDoor)")
  public void aopPoint() {
  }

  @Around("aopPoint()")
  public Object doRouter(ProceedingJoinPoint point) throws Throwable {
//获取内容
    Method method = getMethod(point);
    DoDoor door = method.getAnnotation(DoDoor.class);
    // 获取字段
    String keyValue = getFiledValue(door.key(), point.getArgs());
    logger.info("itstack door handler method：{} value：{}", method.getName(), keyValue);
    if (null == keyValue || "".equals(keyValue)) {
      return point.proceed();
    }

    //配置内容
    String[] split = starterService.split(",");
    //白名单过滤
    for (String str : split) {
      if (keyValue.equals(str)) {
        return point.proceed();
      }
    }
    //拦截
    return returnObject(door, method);
  }

  private Method getMethod(JoinPoint jp) throws NoSuchMethodException {
    Signature signature = jp.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
//    return methodSignature.getMethod();
    Method method = getClass(jp).getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
    return method;
  }

  private Class<? extends Object> getClass(JoinPoint jp) {
    return jp.getTarget().getClass();
  }

  /**
   * 返回烂借口的转换对象,当非白名单用户访问时，会返回一些提示信息
   *
   * @param doGate
   * @param method
   * @return
   * @throws IllegalAccessException
   * @throws InstantiationException
   */
  private Object returnObject(DoDoor doGate, Method method) throws IllegalAccessException, InstantiationException {
    Class<?> returnType = method.getReturnType();
    String returnJson = doGate.returnJson();
    if ("".equals(returnJson)) {
      return returnType.newInstance();
    }
    return JSON.parseObject(returnJson, returnType);
  }

  /**
   * 获取属性值
   * 获取指定kety, 就是获取如惨重的某个属性。这里主要是获取用户ID,通过ID进行拦截
   *
   * @param filed
   * @param arg
   * @return
   */
  private String getFiledValue(String filed, Object[] arg) {
    String filedValue = null;
    for (Object obj : arg) {
      try {
        if (null == filedValue || "".equals(filedValue)) {
          filedValue = BeanUtils.getProperty(arg, filed);
        }
      } catch (Exception e) {
        if (arg.length == 1) {
          return arg[0].toString();
        }
      }
    }
    return filedValue;
  }

}
